package cn.com.godliu.gatewaydemo1.utils;

import lombok.extern.slf4j.Slf4j;
import org.apache.http.*;
import org.apache.http.client.HttpClient;
import org.apache.http.client.HttpRequestRetryHandler;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.protocol.HttpClientContext;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.TrustStrategy;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.ssl.SSLContextBuilder;
import org.apache.http.util.EntityUtils;

import javax.net.ssl.SSLContext;
import java.io.IOException;
import java.io.InterruptedIOException;
import java.net.SocketTimeoutException;
import java.net.UnknownHostException;
import java.nio.charset.StandardCharsets;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

@Slf4j
public class HttpClientUtil {

    //从连接池中获取连接
    private static final int timeoutConnectionRequest = 3000;
    //建立连接
    private static final int timeoutConnect = 3000;
    //数据传输
    private static final int timeoutSocketTimeout = 10000;

    private final static PoolingHttpClientConnectionManager POOLCONNMANAGER = new PoolingHttpClientConnectionManager();

    private final static HttpRequestRetryHandler HTTPREQUESTRETRYHANDLER = (exception, executionCount, context) -> {
        if (executionCount >= 3) {
            return false;
        }
        if (exception instanceof NoHttpResponseException) {
            return true;
        }
        if (exception instanceof InterruptedIOException) {
            return false;
        }
        if (exception instanceof UnknownHostException) {
            return false;
        }
        HttpClientContext clientContext = HttpClientContext.adapt(context);
        HttpRequest request = clientContext.getRequest();

        return !(request instanceof HttpEntityEnclosingRequest);
    };

    static {   //类加载的时候 设置最大连接数 和 每个路由的最大连接数
        POOLCONNMANAGER.setMaxTotal(500);
        POOLCONNMANAGER.setDefaultMaxPerRoute(100);
    }

    @SuppressWarnings("resource")
    public static String doPost(String url, String jsonstr, String charset) {
        HttpClient httpClient = null;
        HttpPost httpPost = null;
        String result = null;
        try {
            httpClient = new SSLClient();
            httpPost = new HttpPost(url);
            httpPost.setHeader("Accept", "application/json");
            httpPost.setHeader("Content-Type", "application/json");
            StringEntity se = new StringEntity(jsonstr, StandardCharsets.UTF_8);
            httpPost.setEntity(se);
            RequestConfig requestConfig = RequestConfig.custom().setConnectionRequestTimeout(timeoutConnectionRequest)
                    .setConnectTimeout(timeoutConnect)
                    .setSocketTimeout(timeoutSocketTimeout).build();//设置请求和传输超时时间
            httpPost.setConfig(requestConfig);
            long stime = System.currentTimeMillis();
            HttpResponse response = httpClient.execute(httpPost);
            if (response != null) {
                HttpEntity resEntity = response.getEntity();
                if (resEntity != null) {
                    result = EntityUtils.toString(resEntity, charset);
                }
            }
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return result;
    }

    public static String doGet(String url, String charset) {
        //创建HttpClient对象
        CloseableHttpClient httpClient = HttpClientBuilder.create().build();
        HttpGet httpGet = new HttpGet(url);
        try {
            HttpResponse response = httpClient.execute(httpGet);
            if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
                //返回json格式
                String res = EntityUtils.toString(response.getEntity(), charset);
                return res;
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    public static String doGet(String url, String charset, Map<String, String> headers) {
        HttpClient httpClient = null;
        HttpGet httpGet = null;
        String result = null;
        try {
            httpClient = new SSLClient();
            httpGet = new HttpGet(url);
            //httpGet.addHeader("Content-Type", "application/json");
            Set keySet = headers.entrySet();
            Iterator iterator = keySet.iterator();
            while (iterator.hasNext()) {
                Map.Entry key = (Map.Entry) iterator.next();
                httpGet.addHeader(String.valueOf(key.getKey()), String.valueOf(key.getValue()));
            }
            RequestConfig requestConfig = RequestConfig.custom().setConnectionRequestTimeout(timeoutConnectionRequest)
                    .setConnectTimeout(timeoutConnect)
                    .setSocketTimeout(timeoutSocketTimeout).build();//设置请求和传输超时时间
            httpGet.setConfig(requestConfig);
            long stime = System.currentTimeMillis();
            HttpResponse response = httpClient.execute(httpGet);
            if (response != null) {
                HttpEntity resEntity = response.getEntity();
                if (resEntity != null) {
                    result = EntityUtils.toString(resEntity, charset);
                }
            }
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return result;
    }

    public static String doGetCache(String url, String charset) {
        HttpGet httpGet = null;
        String result = "";
        CloseableHttpClient closeableHttpClient = createSSLClientDefault();
        try {
            RequestConfig requestConfig = RequestConfig.custom()
                    .setConnectionRequestTimeout(timeoutConnectionRequest)
                    .setConnectTimeout(timeoutConnect)
                    .setSocketTimeout(timeoutSocketTimeout).build();
            httpGet = new HttpGet(url);
            httpGet.setConfig(requestConfig);
            httpGet.addHeader("Content-Type", "application/json");
            long stime = System.currentTimeMillis();
            HttpResponse response = closeableHttpClient.execute(httpGet);
            if (response != null) {
                HttpEntity resEntity = response.getEntity();
                if (resEntity != null) {
                    result = EntityUtils.toString(resEntity, charset);
                }
            }
        } catch (SocketTimeoutException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {

        }

        return result;
    }

    public static String doPostCache(String url, String jsonstr, String charset) {
        CloseableHttpClient httpClient = null;
        HttpPost httpPost = null;
        String result = "";
        try {
            httpClient = createSSLClientDefault();
            httpPost = new HttpPost(url);
            RequestConfig requestConfig = RequestConfig.custom()
                    .setConnectionRequestTimeout(timeoutConnectionRequest)
                    .setConnectTimeout(timeoutConnect)
                    .setSocketTimeout(timeoutSocketTimeout).build();
            httpPost.setConfig(requestConfig);
            httpPost.setHeader("Accept", "application/json");
            httpPost.setHeader("Content-Type", "application/json");
            StringEntity se = new StringEntity(jsonstr, StandardCharsets.UTF_8);
            httpPost.setEntity(se);
            HttpResponse response = httpClient.execute(httpPost);
            if (response != null) {
                HttpEntity resEntity = response.getEntity();
                if (resEntity != null) {
                    result = EntityUtils.toString(resEntity, charset);
                }
            }
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return result;
    }

    @SuppressWarnings("deprecation")
    public static CloseableHttpClient createSSLClientDefault() {
        try {
            SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(null, new TrustStrategy() {
                //信任所有
                public boolean isTrusted(X509Certificate[] chain,
                                         String authType) throws CertificateException {
                    return true;
                }
            }).build();
            SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext);
            return HttpClients.custom().setSSLSocketFactory(sslsf).build();
        } catch (KeyManagementException e) {
            e.printStackTrace();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (KeyStoreException e) {
            e.printStackTrace();
        }
        return HttpClients.createDefault();
    }
}
